package com.example.mq.mqsever.datacenter;

import com.example.mq.MqApplication;
import com.example.mq.common.Consumer;
import com.example.mq.common.MqException;
import com.example.mq.mqsever.VirtualHost;
import com.example.mq.mqsever.core.BasicProperties;
import com.example.mq.mqsever.core.Exchangetype;
import com.example.mq.mqsever.core.MSGQueue;
import javafx.scene.media.VideoTrack;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-09-06
 * Time: 17:22
 */
@SpringBootTest
public class VirtualHosts {
    private VirtualHost virtualHost=null;

    @BeforeEach
    public void setUp(){
        MqApplication.context= SpringApplication.run(MqApplication.class);
        virtualHost=new VirtualHost("default");
    }
    @AfterEach
    public void tearDown() throws IOException {
        MqApplication.context.close();
        virtualHost=null;
        //把硬盘的目录删除掉
        File dataDir=new File("./data");
        FileUtils.deleteDirectory(dataDir);
    }

    @Test
    public void testExchangeDeclare(){
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
    }

    @Test
    public void testExchangeDelete(){
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);

       ok= virtualHost.exchangeDelete("testExchange");
        Assertions.assertTrue(ok);
    }

    @Test
    public void testQueueDeclare(){
        boolean ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);
    }

    @Test
    public void testQueueDelete(){
        boolean ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);

        ok=virtualHost.queueDelete("testQueue");
        Assertions.assertTrue(ok);
    }
    @Test
    public void  testQueueBind(){
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
        ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);

        ok=virtualHost.queueBind("testQueue","testExchange","testBindingKey");
        Assertions.assertTrue(ok);
    }

    @Test
    public void testQueueUnbind(){
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
        ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);


        ok=virtualHost.queueBind("testQueue","testExchange","testBindingKey");
        Assertions.assertTrue(ok);

        ok=virtualHost.queueUnbind("testQueue","testExchange");

        Assertions.assertTrue(ok);
    }

    @Test
    public void testBasicPublish(){
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
        ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);


        ok=virtualHost.basicPublish("testExchange","testQueue",null,
                "hello".getBytes());

        Assertions.assertTrue(ok);

    }
    //先订阅队列,再发送消息
    @Test
    public void testBasicConsume1() throws InterruptedException {
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
        ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);

        //先订阅队列(消费者调用)
        ok=virtualHost.basicConsume("testConsumeTag", "testQueue", true, new Consumer() {
            @Override
            public void handlerDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) {
                //消费者自身设置的回调方法
                System.out.println("messageId="+basicProperties.getMessageId());
                //body是一个字符数组,要转换成字符串打印
                System.out.println("body="+new String(body,0, body.length));


                Assertions.assertEquals("testQueue",basicProperties.getRoutingKey());
                Assertions.assertEquals(1,basicProperties.getDeliverMode());
                Assertions.assertArrayEquals("hello".getBytes(),body);
            }
        });
        //证明一下这个方法本身也是正确的
        Assertions.assertTrue(ok);

        Thread.sleep(500);


        //再发送消息

        ok=virtualHost.basicPublish("testExchange","testQueue",null,
                "hello".getBytes());

        Assertions.assertTrue(ok);

    }

    @Test
    public void testBasicConsume2() throws InterruptedException {
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
        ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);

        //先发送消息

        ok=virtualHost.basicPublish("testExchange","testQueue",null,
                "hello".getBytes());

        Assertions.assertTrue(ok);



        //再订阅队列(消费者调用)
        ok=virtualHost.basicConsume("testConsumeTag", "testQueue", true, new Consumer() {
            @Override
            public void handlerDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) {
                //消费者自身设置的回调方法
                System.out.println("messageId="+basicProperties.getMessageId());
                //body是一个字符数组,要转换成字符串打印
                System.out.println("body="+new String(body,0, body.length));


                Assertions.assertEquals("testQueue",basicProperties.getRoutingKey());
                Assertions.assertEquals(1,basicProperties.getDeliverMode());
                Assertions.assertArrayEquals("hello".getBytes(),body);
            }
        });
        //证明一下这个方法本身也是正确的
        Assertions.assertTrue(ok);

        Thread.sleep(500);
    }

    //针对FANOUT交换机

    @Test
    public void testBasicFanout() throws InterruptedException {
        boolean ok=virtualHost.exchangeDeclare("testExchange",Exchangetype.FANOUT,false,false,null);
        Assertions.assertTrue(ok);

        ok=virtualHost.queueDeclare("testQueue1",false,false,false,null);
        Assertions.assertTrue(ok);

        ok=virtualHost.queueBind("testQueue1","testExchange","");
        Assertions.assertTrue(ok);


        ok=virtualHost.queueDeclare("testQueue2",false,false,false,null);
        Assertions.assertTrue(ok);

        ok=virtualHost.queueBind("testQueue2","testExchange","");
        Assertions.assertTrue(ok);

//往交换机中发布一个消息

        ok=virtualHost.basicPublish("testExchange","",null,"hello".getBytes());
        Assertions.assertTrue(ok);

        Thread.sleep(500);
        //两个消费者订阅两个队列
        ok=virtualHost.basicConsume("testConsumer1", "testQueue1", true, new Consumer() {
            @Override
            public void handlerDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) {
                System.out.println("consumerTag="+consumerTag);
                System.out.println("messageId="+basicProperties.getMessageId());
                Assertions.assertArrayEquals("hello".getBytes(),body);
            }
        });
        Assertions.assertTrue(ok);

        ok=virtualHost.basicConsume("testConsumer2", "testQueue2", true, new Consumer() {
            @Override
            public void handlerDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) {
                System.out.println("consumerTag="+consumerTag);
                System.out.println("messageId="+basicProperties.getMessageId());
                Assertions.assertArrayEquals("hello".getBytes(),body);
            }
        });
        Assertions.assertTrue(ok);
        Thread.sleep(500);


    }

    //验证Topic交换机
    @Test
    public void testBasicConsumeTopic() throws InterruptedException {
        boolean ok=virtualHost.exchangeDeclare("testExchange",Exchangetype.TOPIC,false,false,null);
        Assertions.assertTrue(ok);


        ok=virtualHost.queueDeclare("testQueue",false,false,false,null);
        Assertions.assertTrue(ok);

        ok=virtualHost.queueBind("testQueue","testExchange","aaa.*.bbb");
        Assertions.assertTrue(ok);

        ok=virtualHost.basicPublish("testExchange","aaa.ccc.bbb",null,"hello".getBytes());
        Assertions.assertTrue(ok);

        ok=virtualHost.basicConsume("testConsumer", "testQueue", true, new Consumer() {
            @Override
            public void handlerDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) {
                System.out.println("consumerTag="+consumerTag);
                System.out.println("messageId="+basicProperties.getMessageId());
                Assertions.assertArrayEquals("hello".getBytes(),body);
            }
        });
        Assertions.assertTrue(ok);

        Thread.sleep(500);
    }

    @Test
    public void testBasicAck() throws InterruptedException {
        boolean ok=virtualHost.exchangeDeclare("testExchange", Exchangetype.DIRECT,
                true,false,null);
        Assertions.assertTrue(ok);
        ok=virtualHost.queueDeclare("testQueue",true,false,
                false,null);
        Assertions.assertTrue(ok);

        //先发送消息

        ok=virtualHost.basicPublish("testExchange","testQueue",null,
                "hello".getBytes());

        Assertions.assertTrue(ok);



        //再订阅队列(消费者调用)
        //auto改成false
        ok=virtualHost.basicConsume("testConsumeTag", "testQueue", false, new Consumer() {
            @Override
            public void handlerDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) throws ClassNotFoundException {
                //消费者自身设置的回调方法
                System.out.println("messageId="+basicProperties.getMessageId());
                //body是一个字符数组,要转换成字符串打印
                System.out.println("body="+new String(body,0, body.length));


                Assertions.assertEquals("testQueue",basicProperties.getRoutingKey());
                Assertions.assertEquals(1,basicProperties.getDeliverMode());
                Assertions.assertArrayEquals("hello".getBytes(),body);

                //要改的地方,手动调动ack
                boolean ok=virtualHost.basicAck("testQueue",basicProperties.getMessageId());
                Assertions.assertTrue(ok);
            }
        });
        //证明一下这个方法本身也是正确的
        Assertions.assertTrue(ok);

        Thread.sleep(500);



    }
}
